package com.guahao.portal.swagger.dubbo.web;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Lists;
import com.guahao.portal.swagger.dubbo.config.DubboPropertyConfig;
import com.guahao.portal.swagger.dubbo.config.DubboServiceScanner;
import com.guahao.portal.swagger.dubbo.config.SwaggerDocCache;
import com.guahao.portal.swagger.dubbo.reader.Reader;
import io.swagger.annotations.Api;
import io.swagger.config.SwaggerConfig;
import io.swagger.models.Swagger;
import io.swagger.models.Tag;
import io.swagger.util.Json;
import io.swagger.util.ReflectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("${swagger.dubbo.doc:swagger-dubbo}")
@Api(hidden = true)
public class SwaggerDubboController {

    @Autowired
    private DubboServiceScanner dubboServiceScanner;
    @Autowired
    private DubboPropertyConfig dubboPropertyConfig;
    @Autowired
    private SwaggerDocCache swaggerDocCache;

    @Value("${swagger.dubbo.http:h}")
    private String httpContext;
    @Value("${swagger.dubbo.enable:true}")
    private boolean enable = true;

    @RequestMapping(value = "/swagger.json", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
    @ResponseBody
    public ResponseEntity<String> getApiList() throws JsonProcessingException {
        if (!enable) {
            return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
        }

        Swagger swagger = swaggerDocCache.getSwagger();
        if (null != swagger) {
            return new ResponseEntity<String>(Json.mapper().writeValueAsString(swagger), HttpStatus.OK);
        } else {
            swagger = new Swagger();
        }

        final SwaggerConfig configurator = dubboPropertyConfig;
        if (configurator != null) {
            configurator.configure(swagger);
        }

        Map<Class<?>, Object> interfaceMapRef = dubboServiceScanner.interfaceMapRef();
        if (null != interfaceMapRef) {
            Reader.read(swagger, interfaceMapRef, httpContext);
        }

        // 获取 io.swagger.annotations.Api 注解，构造tags
        List<Tag> tags = Lists.newArrayList();
        for (Class<?> clz : interfaceMapRef.keySet()) {
            Api anno = ReflectionUtils.getAnnotation(clz, Api.class);
            if (null != anno) {
                Tag tag = new Tag();
                tag.setName(clz.getSimpleName());
                tag.setDescription(anno.value());
                tags.add(tag);
            }
        }
        swagger.setTags(tags);

        swaggerDocCache.setSwagger(swagger);
        return new ResponseEntity<String>(Json.mapper().writeValueAsString(swagger), HttpStatus.OK);
    }

}
